﻿#include "utilities.h"

#include <random>
#include <ranges>

#include <vsg/maths/common.h>

vsg::vec4 ColorFromHSV(double hue, double saturation, double value)
{
    vsg::vec4 color = { 0.f, 0.f, 0.f, 1.f };

    // Red channel
    double k = fmod((5.0f + hue / 60.0f), 6);
    double t = 4.0f - k;
    k = (t < k) ? t : k;
    k = (k < 1) ? k : 1;
    k = (k > 0) ? k : 0;
    color.r = value - value * saturation * k;

    // Green channel
    k = fmod((3.0f + hue / 60.0f), 6);
    t = 4.0f - k;
    k = (t < k) ? t : k;
    k = (k < 1) ? k : 1;
    k = (k > 0) ? k : 0;
    color.g = value - value * saturation * k;

    // Blue channel
    k = fmod((1.0f + hue / 60.0f), 6);
    t = 4.0f - k;
    k = (t < k) ? t : k;
    k = (k < 1) ? k : 1;
    k = (k > 0) ? k : 0;
    color.b = value - value * saturation * k;

    return color;
}

vsg::dvec3 ColorToHSV(vsg::vec4 color)
{
    vsg::dvec3 hsv = { 0.f, 0.f, 0.f };
    vsg::dvec3 rgb = { color.r, color.g, color.b };
    double min, max, delta;

    min = rgb.x < rgb.y ? rgb.x : rgb.y;
    min = min < rgb.z ? min : rgb.z;

    max = rgb.x > rgb.y ? rgb.x : rgb.y;
    max = max > rgb.z ? max : rgb.z;

    hsv.z = max;            // Value
    delta = max - min;

    if (delta < 0.00001f)
    {
        hsv.y = 0.0f;
        hsv.x = 0.0f;       // Undefined, maybe NAN?
        return hsv;
    }

    if (max > 0.0f)
    {
        // NOTE: If max is 0, this divide would cause a crash
        hsv.y = (delta / max);    // Saturation
    }
    else
    {
        // NOTE: If max is 0, then r = g = b = 0, s = 0, h is undefined
        hsv.y = 0.0f;
        hsv.x = NAN;        // Undefined
        return hsv;
    }

    // NOTE: Comparing double values could not work properly
    if (rgb.x >= max)
        hsv.x = (rgb.y - rgb.z) / delta;    // Between yellow & magenta
    else
    {
        if (rgb.y >= max)
            hsv.x = 2.0f + (rgb.z - rgb.x) / delta;  // Between cyan & yellow
        else
            hsv.x = 4.0f + (rgb.x - rgb.y) / delta;      // Between magenta & cyan
    }

    hsv.x *= 60.0f;     // Convert to degrees

    if (hsv.x < 0.0f)
        hsv.x += 360.0f;

    return hsv;
}

vsg::dvec3 Polar3DToXYZRandom(Polar3D polar)
{
    double RadAlpha = vsg::radians(polar.alpha);
    double RadBeta = vsg::radians(polar.beta);
    std::random_device rd;  // 将用于获得随机数引擎的种子
    std::mt19937_64 gen(rd()); // 以 rd() 播种的标准 mersenne_twister_engine
    std::normal_distribution<> d{ 5, 10 };
    double z = polar.length * sin(RadAlpha) + d(gen);
    double xy = polar.length * cos(RadAlpha);
    double x = xy * cos(RadBeta) + d(gen);
    double y = xy * sin(RadBeta) + d(gen);
    return { x, y, z };
}

vsg::dvec3 Polar3DToXYZ(Polar3D polar)
{
    double RadAlpha = vsg::radians(polar.alpha);
    double RadBeta = vsg::radians(polar.beta);
    double z = polar.length * sin(RadAlpha);
    double xy = polar.length * cos(RadAlpha);
    double x = xy * cos(RadBeta);
    double y = xy * sin(RadBeta);
    return { x, y, z };
}

std::pair<vsg::dvec3, vsg::dvec3> getOtherNormal(vsg::dvec3 normal)
{
    vsg::dvec3 a = cross(normal, { 1, 0, 0 });
    if (a.x == 0 && a.y == 0 && a.z == 0)
    {
        a = cross(normal, { 0, 1, 0 });
    }
    vsg::dvec3 b = cross(normal, a);
    a = normalize(a);
    b = normalize(b);
    return { a, b };
}

// 获取给定圆心、半径、点数的同z平面圆
std::vector<vsg::dvec3> genCirclePos(vsg::dvec3 center, double radius, uint8_t posCount)
{
    double theta = 0;
    double deltTheta = 360. / posCount;
    std::vector<vsg::dvec3> res{ posCount };
    for (auto i : std::views::iota(0) | std::views::take(posCount))
    {
        double radTheta = vsg::radians(theta);
        double x = center.x + radius * sin(radTheta);
        double y = center.y + radius * cos(radTheta);
        double z = center.z;
        res[i] = { x, y, z };
        theta += deltTheta;
    }
    return res;
}

// 获取给定任意法向量以及圆心、半径的圆离散点
std::vector<vsg::dvec3> getNormalCirclePos(vsg::dvec3 circlePos, double radius, vsg::dvec3 normal, double startAngle, double endAngle, uint8_t pointCount)
{
    std::vector<vsg::dvec3> res{ pointCount };
    auto [a, b] = getOtherNormal(normal);
    double deltAngle = (endAngle - startAngle) / pointCount;
    double alphaDeg = startAngle;
    vsg::dvec3 pointPos;
    double alpha;
    //  for (int i = 0; i < pointCount; ++i) {
    //      alpha = vsg::radians(alphaDeg;
    //      pointPos.x = circlePos.x + radius * a.x * cos(alpha) + radius * b.x * sin(alpha);
    //      pointPos.y = circlePos.y + radius * a.y * cos(alpha) + radius * b.y * sin(alpha);
    //      pointPos.z = circlePos.z + radius * a.z * cos(alpha) + radius * b.z * sin(alpha);
    //      alphaDeg += deltAngle;
    //      res[i] = pointPos;
    //  }
    for (auto i : std::views::iota(0) | std::views::take(pointCount))
    {
        alpha = vsg::radians(alphaDeg);
        pointPos.x = circlePos.x + radius * a.x * cos(alpha) + radius * b.x * sin(alpha);
        pointPos.y = circlePos.y + radius * a.y * cos(alpha) + radius * b.y * sin(alpha);
        pointPos.z = circlePos.z + radius * a.z * cos(alpha) + radius * b.z * sin(alpha);
        alphaDeg += deltAngle;
        res[i] = pointPos;
    }
    return res;
}

std::vector<vsg::dvec3> getRosebushPos(vsg::dvec3 rosebushPos, vsg::dvec3 normal, double radius, uint8_t bushCount)
{
    auto [normalX, normalY] = getOtherNormal(normal);
    vsg::dmat3 modelCoordinateAxisBase =
    {
        normalX.x, normalY.x, normal.x,
        normalX.y, normalY.y, normal.y,
        normalX.z, normalY.z, normal.z
    };

    // r = cos(a*theta);
    // x = r*cos(theta)
    // y = r*sin(theta)
    // z = a/2*sin(a*theta) Or z = r*sin(a*theta) Or z = 0
    int pointCount = 200 * bushCount;
    double deltTheta = 360. / pointCount;
    double theta = 0;
    std::vector<vsg::dvec3> res(pointCount);
    vsg::dvec3 pointPos;
    double thetaRad;
    for (auto i : std::views::iota(0) | std::views::take(pointCount))
    {
        thetaRad = vsg::radians(theta);
        theta += deltTheta;
        double r = radius * cos(bushCount * thetaRad);
        pointPos = { r * cos(thetaRad), r * sin(thetaRad), 0 };
        pointPos = modelCoordinateAxisBase * pointPos;
        pointPos = pointPos + rosebushPos;
        res[i] = pointPos;
    }

    return res;
}

std::vector<vsg::dvec3> getNormalConePos(vsg::dvec3 circlePos, vsg::dvec3 vertexPos, double radius)
{
    std::random_device rd;  // 将用于获得随机数引擎的种子
    std::mt19937_64 gen(rd()); // 以 rd() 播种的标准 mersenne_twister_engine
    std::uniform_int_distribution<> heightCountDis(-10, 10);
    std::uniform_int_distribution<> alphaCountDis(10, 20);
    std::vector<vsg::dvec3> res;
    vsg::dvec3 normal = vertexPos - circlePos;
    vsg::dvec3 normalizationNormal = normalize(normal);
    auto [a, b] = getOtherNormal(normalizationNormal);
    double height = length(normal);
    uint8_t heightCount = 20 + heightCountDis(gen);
    uint8_t circleCount = 20 + alphaCountDis(gen);
    double deltHeight = height / (heightCount - 1);
    double deltAngle = 360.0f / circleCount;
    double angle = 0.0f;
    double heightNow = 0.0;
    vsg::dvec3 pointPos;
    for (int i = 0; i < heightCount; ++i)
    {
        for (int j = 0; j < circleCount; ++j)
        {
            double alpha = vsg::radians(angle);
            pointPos.x = circlePos.x + radius * a.x * cos(alpha) + radius * b.x * sin(alpha);
            pointPos.y = circlePos.y + radius * a.y * cos(alpha) + radius * b.y * sin(alpha);
            pointPos.z = circlePos.z + radius * a.z * cos(alpha) + radius * b.z * sin(alpha);
            angle += deltAngle;
            res.push_back(pointPos);
        }
        heightNow += deltHeight;
        circlePos = circlePos + normalizationNormal * heightNow;
        radius = radius * (height - heightNow) / height;
    }
    return res;
}

vsg::dvec3 getRandomNormal(double startAlpha, double endAlpha, double startBeta, double endBeta)
{
    std::random_device rd;  // 将用于获得随机数引擎的种子
    std::mt19937_64 gen(rd()); // 以 rd() 播种的标准 mersenne_twister_engine
    std::uniform_real_distribution<double> alphaDis(startAlpha, endAlpha);
    std::uniform_real_distribution<double> betaDis(startBeta, endBeta);

    return Polar3DToXYZ({ 1, alphaDis(gen), betaDis(gen) });
}

vsg::vec4 getRandomColor()
{
    std::random_device rd;  // 将用于获得随机数引擎的种子
    std::mt19937_64 gen(rd()); // 以 rd() 播种的标准 mersenne_twister_engine
    std::uniform_real_distribution<double> colorHDis{ 0, 360 };


    double H = colorHDis(gen);
    double S = 1;
    double V = 0.2;
    vsg::vec4 color = ColorFromHSV(H, S, V);
    return color;
}

std::vector<vsg::dvec3> getBallPos(vsg::dvec3 ballPos, double radius, uint8_t alphaCount, uint8_t betaCount)
{
    double alpha = 90;
    double deltAlpha = 180. / alphaCount;
    double beta = 0.;
    double deltBeta = 360.0 / betaCount;
    std::vector<vsg::dvec3> res;
    for (int i = 0; i <= alphaCount; ++i)
    {
        for (int j = 0; j < betaCount; ++j)
        {

            vsg::dvec3 relatePos = Polar3DToXYZ(
            {
                radius, alpha, beta
            });
            vsg::dvec3 pointPos = ballPos + relatePos;
            res.push_back(pointPos);

            beta += deltBeta;
        }
        alpha -= deltAlpha;
    }
    return res;
}

bool isToDo(double iterRatio)
{
    std::random_device rd;  // 将用于获得随机数引擎的种子
    std::mt19937_64 gen(rd()); // 以 rd() 播种的标准 mersenne_twister_engine
    std::uniform_real_distribution<double> iterIsDis(0, 1);
    if (iterIsDis(gen) > iterRatio)
    {
        return true;
    }
    else
    {
        return false;
    }
    return true;
}

std::vector<vsg::dvec3> getHeartPos(vsg::dvec3 heartPos, vsg::dvec3 normal, double radius, uint8_t pointCount)
{
    std::vector<vsg::dvec3> res;
    return res;
}
